#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include<string>
#include<vector>
#include<iostream>
#include<thread>
#include"Thread.hpp"
using namespace ThreadModule;


class ThreadData
{
public:
    ThreadData(int &tickets, const std::string &name, pthread_mutex_t &mutex)
        : _tickets(tickets), _name(name), _total(0), _mutex(mutex)
    {
    }
    ~ThreadData()
    {
    }

public:
    int &_tickets; // 所有的线程，最后都会引用同一个全局的g_tickets
    std::string _name;
    int _total;
    pthread_mutex_t &_mutex;
};

int g_tickets = 10000;// 共享资源，没有保护的, 临界资源
//pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;
void *route(ThreadData *td)
{
    while ( 1 ) 
    {
        //访问临界资源的代码，叫做临界区！
        //--- 我们加锁，本质就是把并行执行 --- 串行执行 --- 加锁的粒度要约细越好
        //pthread_mutex_lock(&gmutex); 

        // 加锁 : 
        //竞争锁是自由竞争的，竞争锁的能力太强的线程，会导致其他线程抢不到锁 
        //--- 造成了其他线程的饥饿问题！

        pthread_mutex_lock(&td->_mutex); 
        if (td->_tickets > 0 ) 
        {
            usleep(1000);
            printf("%s running, get tickets: %d\n", td->_name.c_str(), td->_tickets); 
            td->_tickets--;
            //pthread_mutex_unlock(&gmutex); // 解锁
            pthread_mutex_unlock(&td->_mutex); // 解锁                                                           
            td->_total++;
        } 

        else 
        {
            //pthread_mutex_unlock(&gmutex); // 解锁
             pthread_mutex_unlock(&td->_mutex); // 解锁 
            break;
        }
    }

    return NULL;
}

const int num = 4;
int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);

    std::vector<Thread<ThreadData *>> threads;
    std::vector<ThreadData *> datas;
    // 1. 创建一批线程
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        ThreadData *td = new ThreadData(g_tickets, name, mutex);
        threads.emplace_back(route, td, name);
        datas.emplace_back(td);
    }

    // 2. 启动 一批线程
    for (auto &thread : threads)
    {
        thread.Start();
    }

    // 3. 等待一批线程
    for (auto &thread : threads)
    {
        thread.Join();
        std::cout << "wait thread done, thread is: " << thread.name() << std::endl;
    }


     // 4. 输出统计数据
    for (auto data : datas)
    {
        std::cout << data->_name << " : " << data->_total << std::endl;
        delete data;
    }

    pthread_mutex_destroy(&mutex);
    return 0;
}



















// int main()
// {
//      std::vector<std::thread> threads;
//     // 1. 创建一批线程
//     for (int i = 0; i < 4; i++)
//     {
//         std::string name = "thread-" + std::to_string(i + 1);
//         ThreadData *td = new ThreadData(g_tickets, name);
//         threads.emplace_back(route, td, name);
//         datas.emplace_back(td);
//     }

//     // 2. 启动 一批线程
//     for (auto &thread : threads)
//     {
//         thread.Start();
//     }

//     // 3. 等待一批线程
//     for (auto &thread : threads)
//     {
//         thread.Join();
//         // std::cout << "wait thread done, thread is: " << thread.name() << std::endl;
//     }
    
//     return 0;
// }







